<script>
import { uid } from 'quasar'
import { loadCdnSources } from 'src/utils/cdn.js'
import imageMarkSymbol from 'src/utils/mark-symbol'

function getGeometryObjectMap () {
  const {
    Marker,
    MultiPoint,
    LineString,
    MultiLineString,
    Polygon,
    MultiPolygon
  } = window.maptalks

  return {
    Point: Marker,
    MultiPoint: MultiPoint,
    LineString: LineString,
    MultiLineString: MultiLineString,
    Polygon: Polygon,
    MultiPolygon: MultiPolygon
  }
}

export default {
  name: 'MiniMapViewer',
  props: {
    image: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      id: `u${uid()}`,
      map: null,
      tileLayer: null,
      vectorLayer: null
    }
  },
  mounted () {
    this.init()
  },
  unmounted () {
    this.map.remove()
    this.map = undefined
  },
  methods: {
    async init () {
      if (!this.image.coordinate) {
        return
      }
      await loadCdnSources()
      this.map = this.getMap(this.id)
      this.setTileLayer()
      this.setVectorLayer()
    },
    getMap (id, options) {
      options = Object.assign({}, {
        touchPitch: false,
        touchRotate: false,
        panAnimation: false,
        zoomControl: false,
        doubleClickZoom: false,
        attribution: false,
        repeatWorld: false,
        dragPitch: false,
        dragRotate: false,
        spatialReference: {
          projection: 'identity',
          resolutions: [
            512, 256, 128, 64, 32, 16, 8, 4, 2, 1
          ]
        },
        zoom: 0,
        center: [0, 0]
      }, options)
      const { Map } = window.maptalks
      return new Map(id, options)
    },
    getSize (image) {
      const string = image.tile || image.src
      const [, width, height] = string.match(/_(\d+)_(\d+)\.\S+$/)
      return {
        width: parseInt(width),
        height: parseInt(height)
      }
    },
    getBase64Image (img) {
      const canvas = document.createElement('canvas')
      canvas.width = 256
      canvas.height = 256

      const ctx = canvas.getContext('2d')
      ctx.drawImage(img, 0, 0)

      return canvas.toDataURL('image/png')
    },
    getUrlTemplate (image) {
      if (image.tile) {
        return image.tile
      } else {
        return (x, y, z) => {
          const { width, height } = this.getSize(image)
          const offsetX = x * 256
          const offsetY = y * 256
          const resizeWidth = parseInt(width / Math.pow(2, this.maxZoom - z))
          const resize = this.maxZoom === z ? '' : `/resize,w_${resizeWidth}`

          if (x < 0 || y < 0 || offsetX > width || offsetY > height) {
            return ''
          }

          return `${image.src}?x-oss-process=image${resize}/crop,x_${offsetX},y_${offsetY},w_256,h_256`
        }
      }
    },
    getTileLayer (image) {
      const options = {
        urlTemplate: this.getUrlTemplate(image),
        renderer: 'canvas'
      }
      const getBase64Image = this.getBase64Image
      const { TileLayer } = window.maptalks
      const tileLayer = new TileLayer('tile', options)
      tileLayer.on('renderercreate', (e) => {
        e.renderer.loadTileImage = function (img, url) {
          const remoteImage = new Image()
          remoteImage.crossOrigin = 'anonymous'
          remoteImage.onload = () => {
            img.src = getBase64Image(remoteImage)
          }
          remoteImage.src = url
        }
      })

      return tileLayer
    },
    getSpatialReference (width, height) {
      this.maxZoom = this.getMaxZoom(width, height)
      const resolutions = []
      for (let i = 0; i <= this.maxZoom; i++) {
        resolutions.unshift(Math.pow(2, i))
      }
      return {
        projection: 'identity',
        resolutions
      }
    },
    getMaxZoom (width, height) {
      let edge = width > height ? width : height
      let zoom = 0

      for (let i = 0; i < 20; i++) {
        if (edge / 2 > 512) {
          edge = edge / 2
          zoom += 1
        } else {
          return zoom + 1
        }
      }
    },
    setTileLayer () {
      if (this.tileLayer) {
        this.tileLayer.remove()
      }
      const { width, height } = this.getSize(this.image.image)
      const spatialReference = this.getSpatialReference(width, height)

      this.tileLayer = this.getTileLayer(this.image.image)
      this.map.setSpatialReference(spatialReference)
      // this.map.setCenter(this.image.coordinate.coordinates)
      this.map.setZoom(spatialReference.resolutions.length - 1)
      this.map.addLayer(this.tileLayer)
    },
    setVectorLayer () {
      // 生成图层
      const { VectorLayer } = window.maptalks
      this.vectorLayer = new VectorLayer('vector-layer')
      this.map.addLayer(this.vectorLayer)
      // 绘制点
      const geometryObjectMap = getGeometryObjectMap()
      const feature = this.image.coordinate
      const geometry = new geometryObjectMap[feature.type](feature.coordinates, {
        symbol: imageMarkSymbol[feature.type]
      })
      geometry.addTo(this.vectorLayer)
      if (geometry.type === 'Point') {
        this.map.setCenter(geometry.getCoordinates())
      } else {
        this.map.fitExtent(geometry.getExtent())
      }
    }
  }
}
</script>

<template>
  <div :id="id" class="full-height bg-grey-8 no-pointer-events" />
</template>
